import {
  PluginFunctions,
  PluginOnDocumentLoad,
  RenderViewer,
  ViewerState,
  PluginOnTextLayerRender,
} from "../../core";
import { fullScreenPlugin } from "../full-screen";
import { downloadPlugin } from "../download";
import { openPlugin } from "../open";
import { pageNavigationPlugin } from "../page-navigation";
import { printPlugin } from "../print";
import { propertiesPlugin } from "../properties";
import { rotatePlugin } from "../rotate";
import { scrollModePlugin } from "../scroll-mode";
import { searchPlugin } from "../search";
import { selectionModePlugin } from "../selection-mode";
import { themePlugin } from "../theme";
import { zoomPlugin } from "../zoom";

import Toolbar, { ToolbarProps } from "./Toolbar";

import { ToolbarPlugin, ToolbarPluginProps } from "./interface";

const toolbarPlugin = (props?: ToolbarPluginProps): ToolbarPlugin => {
  const fullScreenPluginInstance = fullScreenPlugin(
    props ? props.fullScreenPlugin : {}
  );
  const downloadPluginInstance = downloadPlugin(
    props ? props.downloadPlugin : {}
  );
  const openPluginInstance = openPlugin();
  const pageNavigationPluginInstance = pageNavigationPlugin();
  const printPluginInstance = printPlugin(props ? props.printPlugin : {});
  const propertiesPluginInstance = propertiesPlugin();
  const rotatePluginInstance = rotatePlugin();
  const scrollModePluginInstance = scrollModePlugin(
    props ? props.scrollModePlugin : {}
  );
  const searchPluginInstance = searchPlugin(props ? props.searchPlugin : {});
  const selectionModePluginInstance = selectionModePlugin(
    props ? props.selectionModePlugin : {}
  );
  const themePluginInstance = themePlugin();
  const zoomPluginInstance = zoomPlugin(props ? props.zoomPlugin : {});

  const plugins = [
    fullScreenPluginInstance,
    downloadPluginInstance,
    openPluginInstance,
    pageNavigationPluginInstance,
    printPluginInstance,
    propertiesPluginInstance,
    rotatePluginInstance,
    scrollModePluginInstance,
    searchPluginInstance,
    selectionModePluginInstance,
    themePluginInstance,
    zoomPluginInstance,
  ];

  const ToolbarDecorator = (props: ToolbarProps) => {
    const {
      EnterFullScreen,
      EnterFullScreenMenuItem,
    } = fullScreenPluginInstance;
    const { Download, DownloadMenuItem } = downloadPluginInstance;
    const { Open, OpenMenuItem } = openPluginInstance;
    const {
      CurrentPageInput,
      CurrentPageLabel,
      GoToFirstPage,
      GoToFirstPageMenuItem,
      GoToLastPage,
      GoToLastPageMenuItem,
      GoToNextPage,
      GoToNextPageMenuItem,
      GoToPreviousPage,
      GoToPreviousPageMenuItem,
    } = pageNavigationPluginInstance;
    const { Print, PrintMenuItem } = printPluginInstance;
    const { ShowProperties, ShowPropertiesMenuItem } = propertiesPluginInstance;
    const {
      Rotate,
      RotateBackwardMenuItem,
      RotateForwardMenuItem,
    } = rotatePluginInstance;
    const {
      SwitchScrollMode,
      SwitchScrollModeMenuItem,
    } = scrollModePluginInstance;
    const { Search, ShowSearchPopover } = searchPluginInstance;
    const {
      SwitchSelectionMode,
      SwitchSelectionModeMenuItem,
    } = selectionModePluginInstance;
    const { SwitchTheme, SwitchThemeMenuItem } = themePluginInstance;
    const {
      CurrentScale,
      Zoom,
      ZoomIn,
      ZoomInMenuItem,
      ZoomOut,
      ZoomOutMenuItem,
    } = zoomPluginInstance;

    const NumberOfPages = () => (
      <CurrentPageLabel>
        {(props) => <>{props.numberOfPages}</>}
      </CurrentPageLabel>
    );

    return (
      <Toolbar
        {...props}
        slot={{
          CurrentPageInput,
          CurrentPageLabel,
          CurrentScale,
          Download,
          DownloadMenuItem,
          EnterFullScreen,
          EnterFullScreenMenuItem,
          GoToFirstPage,
          GoToFirstPageMenuItem,
          GoToLastPage,
          GoToLastPageMenuItem,
          GoToNextPage,
          GoToNextPageMenuItem,
          GoToPreviousPage,
          GoToPreviousPageMenuItem,
          NumberOfPages,
          Open,
          OpenMenuItem,
          Print,
          PrintMenuItem,
          Rotate,
          RotateBackwardMenuItem,
          RotateForwardMenuItem,
          Search,
          ShowProperties,
          ShowPropertiesMenuItem,
          ShowSearchPopover,
          SwitchScrollMode,
          SwitchScrollModeMenuItem,
          SwitchSelectionMode,
          SwitchSelectionModeMenuItem,
          SwitchTheme,
          SwitchThemeMenuItem,
          Zoom,
          ZoomIn,
          ZoomInMenuItem,
          ZoomOut,
          ZoomOutMenuItem,
        }}
      />
    );
  };

  return {
    // Plugin instances
    fullScreenPluginInstance,
    downloadPluginInstance,
    openPluginInstance,
    pageNavigationPluginInstance,
    printPluginInstance,
    propertiesPluginInstance,
    rotatePluginInstance,
    scrollModePluginInstance,
    searchPluginInstance,
    selectionModePluginInstance,
    themePluginInstance,
    zoomPluginInstance,
    install: (pluginFunctions: PluginFunctions) => {
      // Install plugins
      plugins.forEach((plugin) => {
        if (plugin.install) {
          plugin.install(pluginFunctions);
        }
      });
    },
    renderViewer: (props: RenderViewer) => {
      let { slot } = props;
      plugins.forEach((plugin) => {
        if (plugin.renderViewer) {
          slot = plugin.renderViewer({ ...props, slot });
        }
      });
      return slot;
    },
    uninstall: (pluginFunctions: PluginFunctions) => {
      // Unistall plugins
      plugins.forEach((plugin) => {
        if (plugin.uninstall) {
          plugin.uninstall(pluginFunctions);
        }
      });
    },
    onDocumentLoad: (props: PluginOnDocumentLoad) => {
      plugins.forEach((plugin) => {
        if (plugin.onDocumentLoad) {
          plugin.onDocumentLoad(props);
        }
      });
    },
    onTextLayerRender: (props: PluginOnTextLayerRender) => {
      plugins.forEach((plugin) => {
        if (plugin.onTextLayerRender) {
          plugin.onTextLayerRender(props);
        }
      });
    },
    onViewerStateChange: (viewerState: ViewerState) => {
      let newState = viewerState;
      plugins.forEach((plugin) => {
        if (plugin.onViewerStateChange) {
          newState = plugin.onViewerStateChange(newState);
        }
      });
      return newState;
    },
    Toolbar: ToolbarDecorator,
  };
};

export default toolbarPlugin;
